package cn.coder.jdbc;

import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.coder.jdbc.config.JdbcConfig;
import cn.coder.jdbc.config.ResourceConfigFactory;
import cn.coder.jdbc.core.JdbcDataSource;
import cn.coder.jdbc.session.DefaultSqlSession;
import cn.coder.jdbc.session.ProxySession;
import cn.coder.jdbc.util.Assert;

public final class SqlSessionFactory {
	private static final Logger logger = LoggerFactory.getLogger(SqlSessionFactory.class);

	private static final String DEFAULT_SOURCE = "default";
	private static volatile SqlSessionFactory singleton;

	public static SqlSessionFactory getInstance() {
		if (singleton == null) {
			synchronized (SqlSessionFactory.class) {
				if (singleton == null) {
					singleton = new SqlSessionFactory();
				}
			}
		}
		return singleton;
	}

	private final JdbcConfig config;

	private SqlSessionFactory() {
		this.config = new ResourceConfigFactory().parse("jdbc.properties");
	}

	public static void createSessions() {
		getInstance();
	}

	private JdbcConfig getConfig() {
		return this.config;
	}

	/**
	 * 外部DataSource的key默认为default
	 * 
	 * @param dataSource
	 */
	public static void createSession(DataSource dataSource) {
		getInstance().getConfig().addDataSource(DEFAULT_SOURCE, dataSource);
	}

	public SqlSession getSession() {
		return getSession(DEFAULT_SOURCE);
	}

	public SqlSession getSession(String source) {
		Assert.notNull(this.config, "Field 'jdbcConfig' is required");
		return ProxySession.bind(new DefaultSqlSession(this.config, source));
	}

	public synchronized static void destory() {
		long start = System.nanoTime();
		JdbcConfig jdbcConfig = getInstance().getConfig();
		Map<String, DataSource> sources = jdbcConfig.getDataSources();
		for (DataSource source : sources.values()) {
			if (source instanceof JdbcDataSource) {
				((JdbcDataSource) source).close();
			}
		}
		if (logger.isDebugEnabled())
			logger.debug("Sessions destroied: {}ns", (System.nanoTime() - start));
	}
}
